// pages/goods-detail/goods-detail.js

import { equalsObj, msg, navBack } from '@/utils/util'

// Page({
Component({ // 使用Component构建页面，可以使用监听器observers

    data: {
        goods: {}, // 商品信息
        specsAttrs: {}, // 页面展示的规格数据
        selectedSku: {}, // 当前选中的规格对象
        targetSpecs: null, // 商品目标规格对象， 真正需要的
        buyNum: 1, // 购买数量
        notSelectedAtrrNames: [], // 没有选择的规格类型名
    },

    // 注意：上面将 Page 改为了Component后，使用methods中定义生命周期函数和自定义方法
    methods: {
        onLoad(options) {
            const goods = JSON.parse(options.goods || "{}")
            this.setData({ goods })
            // console.log('goods', goods)
    
            wx.setNavigationBarTitle({
              title: goods?.goodsName,
            })
    
            // 将商品规格数据转换成页面中需要展示的格式数据
            this.formatSpecsData()

            // 让第一次触发监听器
            this.setData({selectedSku: {} })
        },
    
        /**
         * 将商品规格数据转换成页面中需要展示的格式数据
         * specsAttrs:
            {
                "份量": [
                    {attrValue: '中杯', able: true},
                    {attrValue: '大杯', able: true}
                ],
                "温度": [
                {attrValue: '常温', able: true},
                {attrValue: '少冰', able: true}
                ]
            }
         */
        formatSpecsData() {
           const { goodsSpecs } = this.data.goods
            if (!goodsSpecs || goodsSpecs.length <= 0) return
    
            // 封装格式化后的规格属性：key规格类型，value是此类型下的所有规格值
            const specsAttrs = {}
            goodsSpecs.forEach(specs => {
                const {specsData} = specs
                // [份量，温度]
                Object.keys(specsData).forEach(key => {
                    const values = specsAttrs[key] || []
                    // 判断当前规格值是否已经存在
                    const exist = values.some(v => v.attrValue == specsData[key])
                    if (!exist) {
                        values.push({attrValue: specsData[key], able: true})
                        specsAttrs[key] = values 
                        // {份量: [{attrValue: specsData[key], able: true}]}
                    }
                })
            })
    
            console.log('specsAttrs', specsAttrs)
            this.setData({specsAttrs})
        },
    
        /**
         * 选择规格值
         * 1. 判断其他类型的值是否可选：可选(able: true)、不可选(able: false)
                可选：如果已经选择过，说明再次点击，则取消选中；反之添加到选择的SKU中
                不可选：选择的SKU对象中只保留当前的规格名称
          2. 再次判断规格是否可以被选择
                循环每个规格类型下的规格值
                循环的每一个规格，与选中sku对象的合并，
                查看合并的sku对象的每个属性，是否在商品规格数据中有相等的属性值的对
                象，且有库存，则可选
          3. 根据选中的sku，查找商品目标规格对象
         */
        changeSpecs(e) {
            const {key, value, able} = e.currentTarget.dataset
            // console.log('key, value, able', key, value, able)
    
            // selectedSku: {份量：大杯，温度：少冰}
            let { goods, specsAttrs, selectedSku = {} } = this.data
    
            // 1. 判断当前点击的规格值是否是可选
            if (able) {
                // 可选：如果已经选择过，说明再次点击，则取消选中；反之添加到选择的SKU中
                if (selectedSku[key] == value) {
                    delete selectedSku[key]
                } else {
                    selectedSku[key] = value
                }
            } else {
                // 不可选：选择的SKU对象中只保留当前的规格名称
                selectedSku = {[key]: value} // {温度: 常温}
            }
    
            // 2. 将当前选中的规格值，与其他规格值一一组合，然后去匹配商品信息中是否存在相同的规格对象
            // 2.1 循环出其他所有的规格值 
            // {"份量"：[{attrValue: 中杯, able: true}, {attrValue: 大杯, able: true}], 
            //  "温度": [{attrValue: 常温, able: true}, {attrValue: 少冰, able: true}}
            const { goodsSpecs } = goods
            for (let attrName in specsAttrs) {
                specsAttrs[attrName].forEach(attr => {
                    // attr 就是每个规格对象
                    // selectedSKU: {份量：中杯}
                    // everySKU:  { 份量：中杯, 份量：中杯 } =》  { 份量：中杯 }
                    // 2次 {份量：中杯, 份量：大杯 } =》 {份量：大杯}
                    // 3次 {份量：中杯, 温度: 常温} =》{份量：中杯, 温度: 常温}
                    // 4次 {份量：中杯, 温度: 少冰} =》{份量：中杯, 温度: 少冰}
                    // 2.2 循环的每一个规格值，与选中sku对象的合并，
                    const everySku = {...selectedSku, [attrName]: attr.attrValue}
                    // console.log('everySku', everySku)
                    // 2.3 将合并后的每个属性，判断是否商品规格数据goodsSpecs中是否有相等的规格对象
                    // 如果有：则还要判断库存是否充足大于0，存在且有库存则可选，否则不可选
                    attr.able = goodsSpecs.some(gs => {
                        return Object.keys(everySku).every(key => gs.specsData[key] == everySku[key] ) && gs.stockNum > 0
                    })
                })
            }
            
            // 根据选中的sku，查找商品目标规格对象
            const targetSpecs = goodsSpecs.find(gs => equalsObj(selectedSku, gs.specsData)) || null
            // 将多个规格值 使用 / 分隔，用于页面展示 
            if (targetSpecs) {
                targetSpecs.specsName = Object.values(targetSpecs.specsData).join('/')
            }
    
            // console.log('targetSepect', targetSpecs)
    
            this.setData({ selectedSku, specsAttrs, targetSpecs })
    
        },
    
        // 获取数量
        changeBuyNum(e) {
            const {detail = 1} = e
            this.setData({ buyNum: detail })
        },

        // 加入购物车
        handleAddCart() {
            const { goods, buyNum, targetSpecs, notSelectedAtrrNames } = this.data

            // 选择的商品信息
            let selectedGoods = { ...goods, buyNum }

            // 多规格商品
            if (goods.goodsSpecs && goods.goodsSpecs.length > 0) {
                if (!targetSpecs || (notSelectedAtrrNames && notSelectedAtrrNames.length > 0)) {
                    msg('请选择商品SKU')
                    return
                }

                // 封装选择的商品规格
                const { 
                    _id: specsId, 
                    price: specsPrice, 
                    specsName,
                    cost, 
                    stockNum
                } = targetSpecs
                // 商品规格单价
                selectedGoods.price = (selectedGoods.price || 0) + (specsPrice || 0)
                // 商品规格特价
                selectedGoods.discountPrice = (selectedGoods.discountPrice || 0) + (specsPrice || 0)
                selectedGoods = {...selectedGoods, specs: targetSpecs, specsId, specsName, cost, stockNum}
            }

            // console.log('sele', selectedGoods)

            // 触发来源页面的事件，传递选择的商品规格
            const eventChannel = this.getOpenerEventChannel()
            eventChannel.emit('addToCart', selectedGoods)
            // 后退回点单页
            navBack()
        }
    
    },

    observers: {
        // 监听选中的规格对象变化 ，来判断是否所有规格类型都选择了规格值
        selectedSku(selectedSku) {
            const { specsAttrs }  = this.data
            const notSelectedAtrrNames = Object.keys(specsAttrs).filter(attrName => !!!selectedSku[attrName])
            this.setData({ notSelectedAtrrNames })
            // console.log('no', notSelectedAtrrNames)
        }
    },
    

})